package edu.geo.filters;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.vividsolutions.jts.geom.Geometry;

import edu.geo.containers.GeoJson;
import edu.geo.containers.Json;
import edu.geo.containers.geom.impl.LineSegment;
import edu.geo.containers.geom.impl.Point;
import edu.geo.containers.geomdomain.GeometricDomain;
import edu.geo.containers.geomdomain.Grid;
import edu.geo.exception.GeoInfoException;
import edu.geo.protocol.Properties;
import edu.geo.protocol.impl.GeomDomainAddResponse;
import edu.geo.service.IGeometricDomainServiceFacade;

public class GeometricDomainAddProcessor extends GeoProcessDecorator {

	private static final Log LOGGER = LogFactory
			.getLog(GeometricDomainAddProcessor.class);

	private IGeometricDomainServiceFacade geomDomainService;

	/*
	 * Permite definir un dominio geométrico.
	 * 
	 * /* {
	 * 
	 * "type": "Operation", "name": "addGeometricDomain", "properties": {
	 * "user": "geoinfouser", "grid": { "originX": "6", "originY": "6",
	 * "numPointsX": "7", "numPointsY": "8", "intSize": "5" }, "geomObjects": {
	 * "type": "GeometryCollection", "geometries": [ { "type": "Point",
	 * "coordinates": [ 21, 11 ] }, { "type": "Point", "coordinates": [ 20, 1 ]
	 * }, { "type": "LineString", "coordinates": [ [ 21, 11 ], [ 20, 1 ] ] } ] }
	 * } }
	 */

	/*
	 * CAMBIAR EL PROTOCOLO
	 * 
	 * 
	 * { "type": "Operation", "name": "DefineDomainGrid", "properties": {
	 * "id":"a", "originX": "0", "originY": "0", "numPointsX": "10",
	 * "numPointsY": "10", "itvX": "1", "itvY": "1" } }
	 */

	public GeometricDomainAddProcessor(
			IGeometricDomainServiceFacade geomDomainService) {
		super();
		this.geomDomainService = geomDomainService;
	}

	@Override
	public Json dispatchResult(Json requestParams) {
		Json result = null;
		try {
			Properties properties = requestParams.getProperties();
			String user = properties.getUser();
			String numPointsXStr = properties.getGrid().getNumPointsX();
			String numPointsYStr = properties.getGrid().getNumPointsY();
			String itvSizeStr = properties.getGrid().getIntSize();

			int numPointsX = (numPointsXStr != null) ? Integer
					.parseInt(numPointsXStr) : Grid.DEFAULT_X;
			int numPointsY = (numPointsYStr != null) ? Integer
					.parseInt(numPointsYStr) : Grid.DEFAULT_Y;
			int itvSize = (itvSizeStr != null) ? Integer.parseInt(itvSizeStr)
					: Grid.DEFAULT_INT_SIZE;
			GeometricDomain geometricDomain = new GeometricDomain();
			if ( properties.getGeomObjects() != null)
			{
				Geometry geometries = properties.getGeomObjects().toGeometry();
				for (int numGeom = 0; numGeom < geometries.getNumGeometries(); ++numGeom) {
					if (geometries.getGeometryN(numGeom) instanceof Point) {
						geometricDomain.addPoint((Point)geometries.getGeometryN(numGeom));	
					} else if (geometries.getGeometryN(numGeom) instanceof LineSegment) {
						geometricDomain.addLineSegment((LineSegment)geometries.getGeometryN(numGeom));	
					}	
				}
			}			
			// Usuario que crea la grilla
			geometricDomain.setUser(user);
			// Especificación de la grilla
			Point point = (Point) properties.getGrid().getOrigin().toGeometry();
			LOGGER.info("str_x: " + point.getX() + " str_y:" + point.getY());
			Grid grid = new Grid(point, numPointsX, numPointsY, itvSize);
			geometricDomain.setGrid(grid);
			int id = geomDomainService.save(geometricDomain);

			result = new Json();
			GeomDomainAddResponse geometryDomainAddResponse = new GeomDomainAddResponse();
			geometryDomainAddResponse
					.setResult(GeomDomainAddResponse.OPERATION_RESULT_SUCCESSFULLY);
			geometryDomainAddResponse.setDomainId(Integer.toString(id));
			result.setName(GeomDomainAddResponse.OPERATION_NAME);
			result.setType("FeatureCollection");
			List<Json> features = new ArrayList<Json>();
			double dgx = itvSize * numPointsX;
			double dgy = itvSize * numPointsY;
			double xo = point.getX() - (dgx / 2);
			double yo = point.getY() - (dgy / 2);
			LOGGER.info("dgx" + dgx);
			LOGGER.info("dgy" + dgy);
			LOGGER.info("xo" + xo);
			LOGGER.info("yo" + yo);
			for (int i = 0; i < numPointsX; i++) {
				for (int j = 0; j < numPointsY; j++) {
					int xp = (int) (xo + (i * itvSize));
					int yp = (int) (yo + (j * itvSize));
					Json feature = new Json();
					feature.setType("Feature");
					GeoJson geometry = new GeoJson();
					geometry.setType("Point");
					ArrayList<Double> coordinates = new ArrayList<Double>();
					coordinates.add((double) xp);
					coordinates.add((double) yp);
					geometry.setCoordinates(coordinates);
					feature.setGeometry(geometry);
					features.add(feature);
				}
			}
			result.setFeatures(features);
			result.setProperties(properties);
			return result;
		} catch (GeoInfoException e) {
			LOGGER.error(e.getMessage(), e);
		}
		return result;
	}
}